using System;
using System.Collections.Generic;
namespace Battle.TimelineLog
{
    /// <summary>
    /// 时间轴战斗
    /// </summary>
    public class Battle
    {
        public BattleTimeLine TimeLine { get; } // 时间轴
        public BattleLog BattleLog { get; } // 战斗的最终log记录
        public VirtualMap Map { get; } // 虚拟数据地图
        public List<ITimeActive> TimeActives { get; } // 根据时间来行动的行动体
        public Team<Fighter> SelfTeam; // 我方队伍
        public Team<Fighter> EnemyTeam; // 敌方队伍
        private int state;// 战斗状态 0:继续; 1:胜利; 2:失败; 3:平局
        public Battle()
        {
            BattleLog = new BattleLog();
            TimeLine = new BattleTimeLine();
            TimeActives = new List<ITimeActive>();
            SelfTeam = new Team<Fighter>(1);
            EnemyTeam = new Team<Fighter>(2);
            Map = new VirtualMap();
        }

        /// <summary>
        /// 初始化战斗
        /// </summary>
        /// <param name="totalTime">总时间，单位：ms</param>
        /// <param name="fighters">所有的参战者初始数据列表</param>
        public void Init(int totalTime, List<InitFighterData> fighters)
        {
            TimeLine.Init(totalTime);

            for (int i = 0; i < fighters.Count; i++)
            {
                var f = fighters[i];
                Fighter fighter = new Fighter(this);
                fighter.Init(f);
                if (f.Side == 1)
                    SelfTeam.Add(fighter);
                else
                    EnemyTeam.Add(fighter);
                InsertTimeActive(fighter);
            }

            // 将时间行动体按顺序升序排列
            TimeActives.Sort((a, b) => a.NextTime - b.NextTime);

            // 初始化log
            BattleLog.Init();

            Console.WriteLine("battle inited!");
        }

        public virtual BattleLogData Start()
        {
            // 如果运算时间过久，可以自行重载成分帧处理
            while (!IsOver())
            {
                Activing();
            }
            return Over();
        }
        protected virtual BattleLogData Over()
        {
            // 如有需要，自行重载返回的数据格式
            Console.WriteLine("battle over!");
            if (state == 3)
                BattleLog.LogData.Winner = 0;
            else if (state == 1)
                BattleLog.LogData.Winner = SelfTeam.Side;
            else if (state == 2)
                BattleLog.LogData.Winner = EnemyTeam.Side;
            return BattleLog.LogData;
        }
        public void Activing()
        {
            ITimeActive act = TimeActives[0];
            if (act == null) throw new Exception("no act");
            if (act.NextTime > TimeLine.TotalTime)
            {
                // 当所有的依托时间的行动体下次行动时间已经超过了最大时间，就结束
                TimeLine.CrtTime = TimeLine.TotalTime;
                return;
            }
            TimeActives.RemoveAt(0);
            if (act.NextTime > TimeLine.CrtTime)
            {
                TimeLine.CrtTime = act.NextTime;
            }
            act.Active();
            InsertTimeActive(act);
        }
        public virtual void InsertTimeActive(ITimeActive act)
        {
            if (act.NextTime <= 0 || act.NextTime > TimeLine.TotalTime) return;
            int idx = TimeActives.Count;
            for (int i = TimeActives.Count - 1; i >= 0; i--)
            {
                ITimeActive a = TimeActives[i];
                if (act.NextTime > a.NextTime)
                {
                    idx = i + 1;
                    break;
                }
            }
            TimeActives.Insert(idx, act);
        }
        public virtual void RemoveTimeActive(ITimeActive act)
        {
            TimeActives.Remove(act);
        }
        public virtual void FighterDead(Fighter fighter)
        {
            SelfTeam.Dead(fighter);
            EnemyTeam.Dead(fighter);
            RemoveTimeActive(fighter);
        }
        public ITimeActive GetTimeActive(int id)
        {
            for (int i = 0, n = TimeActives.Count; i < n; i++)
            {
                if (TimeActives[i].Id == id)
                {
                    return TimeActives[i];
                }
            }
            return null;
        }
        public virtual bool IsOver()
        {
            // 可以自己覆盖定义结束
            state = EnemyTeam.IsLose() ? 1 : 0;
            if (state == 0)
                state = SelfTeam.IsLose() ? 2 : 0;
            if (state == 0)
                state = TimeLine.CrtTime >= TimeLine.TotalTime || TimeActives.Count == 0 ? 3 : 0;
            return state > 0;
        }
    }
}